import {computed, onUnmounted, reactive, ref, type Ref, useSlots, watch} from "vue";
import type {MorghulisTableProps} from "../../types/table/m.table.types";
import type {TablePopper} from "../../types/table/table.types";
import Sortable, {type SortableEvent} from "sortablejs";
import _ from "lodash";
import {$message} from "../../tools/feedback";
import {useClipboard} from "@vueuse/core";

export function useMorghulisTable(table: Ref, props: MorghulisTableProps) {


    const position = ref({} as DOMRect)
    const popover = reactive<TablePopper>({ref: {getBoundingClientRect: () => position.value}})
    const selection = computed(() => table.value?.getSelectionRows())
    const slots = useSlots();

    const hasMetaViewSlot = computed(() => !!slots['pop-meta']);
    const hasSearchSlot = computed(() => !!slots['pop-search']);
    const hasFieldSlot = computed(() => !!slots['pop-field']);

    const hasIndexSlot = computed(() => !!slots['pop-index']);
    const hasCellToolSlot = computed(() => !!slots['pop-cell']);


    const {copy} = useClipboard()

    /**
     * 样式
     */
    function tableCellClassName(data: any) {
        const {column: {type, property}} = data
        if (type !== 'default' || !property) return 'm-table-core-cell'
    }

    function tableRowClassName(payload: any) {
        const rows: any[] = table.value?.getSelectionRows()
        return !rows?.includes(payload.row) ? '' : rows.length === 1 ? 'm-table-current' : 'm-table-highlight'
    }

    /**
     * 点击
     */

    const setSelection = (keys: any[]) => {
        table.value?.clearSelection()
        props.data.forEach((row: any) => {
            if (keys.includes(row.id)) table.value.toggleRowSelection(row)
        })
    }

    function handleCellClick(row: object, column: any, cell: any, event: any) {
        event.preventDefault()
        event.stopPropagation()
        const {type, property} = column
        if (type === 'default' && !property) return
        table.value.toggleRowSelection(row)
    }

    function handleCellContextMenu(row: any, column: any, cell: any, event: any) {
        event.preventDefault()
        event.stopPropagation()
        const {type, property} = column
        if (type === 'default' && !property) return
        table.value.clearSelection(row)
        table.value.toggleRowSelection(row)
        if (type === 'default' && property) {
            if (hasCellToolSlot.value) {
                showPopover(event, 'cell', {row, prop: property})
            } else {
                const value = row[property as string]
                const str = value instanceof Object ? JSON.stringify(value) : value
                copy(str).then(r => $message.info('单元格内容已复制'))
            }
        } else if (type === 'index') {
            hasIndexSlot.value && showPopover(event, 'index', row, 'right')
        }
    }

    /**
     * 弹出
     */

    function showPopover(event: {
        clientX: number,
        clientY: number
    }, type: string, data?: any, placement: string = 'bottom') {
        const {clientX, clientY} = event
        position.value = DOMRect.fromRect({x: clientX, y: clientY})
        popover.visible = true
        popover.type = type
        popover.data = data
        popover.placement = placement
    }

    /**
     * sortable
     */

    let sortable: Sortable | null = null
    watch(() => [props.data, props.view], (nv) => {
        if (!_.isEmpty(props.view)) {
            const disabled = !(props.view.allow_pop)
            init(disabled)
        }
    }, {deep: true})

    function init(disabled: boolean = false) {
        sortable && sortable.destroy()
        const el: HTMLElement = table.value.$el.querySelectorAll('tbody')[0]
        sortable = new Sortable(el, {
            draggable: 'tr.el-table__row',
            handle: '.m-table-current ',
            animation: 150,
            disabled,
            sort: true,
            onEnd(event: SortableEvent) {
                const {newIndex, oldIndex} = event
                /**
                 * 反向操作，拒绝排序！
                 */
                    // @ts-ignore
                const array = this.toArray()
                const curr = array.splice(newIndex, 1)[0]
                array.splice(oldIndex, 0, curr)
                // @ts-ignore
                this.sort(array)

                /**
                 * 清除掉残余的hover-row。
                 */
                Array.from(table.value.$el.querySelectorAll('.el-table__row'))
                    .forEach((row: any) => {
                        row.classList.remove('hover-row')
                    })

                /**
                 * 在回掉函数中完成排序动作。
                 */
                props.sortableCallback
                && props.sortableCallback(newIndex as number, oldIndex as number)
            }
        })
    }

    onUnmounted(() => {
        sortable && sortable.destroy()
    })


    return {
        popover,
        selection,
        tableCellClassName,
        tableRowClassName,
        handleCellClick,
        handleCellContextMenu,
        showPopover,
        closePopover: () => popover.visible = false,
        setSelection,
        hasSearchSlot,
        hasFieldSlot,
        hasMetaViewSlot
    }
}